package com.alan.shiro.api.utils;

import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.MACSigner;
import com.nimbusds.jose.crypto.MACVerifier;
import lombok.extern.slf4j.Slf4j;
import net.minidev.json.JSONObject;

import java.text.ParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @Auther: Alan liu
 * @Date: 2018/12/14 16:28
 * @Description: JwtTokenTest
 */
@Slf4j
public class JwtTokenUtils {

    /**
     * 1.创建一个32-byte的密匙 不能用于32位
     */
    private static final byte[] secret = "geiwodiangasfdjsikolkjikolkijswe111efe".getBytes();

    /**
     * 生成一个token
     * @param payloadMap
     * @return
     * @throws JOSEException
     */
    public static String creatToken(Map<String,Object> payloadMap) throws JOSEException {
        //3.先建立一个头部Header
        /**
         * JWSHeader参数：1.加密算法法则,2.类型，3.。。。。。。。
         * 一般只需要传入加密算法法则就可以。
         * 这里则采用HS256
         *
         * JWSAlgorithm类里面有所有的加密算法法则，直接调用。
         */
        JWSHeader jwsHeader = new JWSHeader(JWSAlgorithm.HS256);
        //建立一个载荷Payload
        Payload payload = new Payload(new JSONObject(payloadMap));
        //将头部和载荷结合在一起
        JWSObject jwsObject = new JWSObject(jwsHeader, payload);
        //建立一个密匙
        JWSSigner jwsSigner = new MACSigner(secret);
        //签名
        jwsObject.sign(jwsSigner);
        //生成token
        return jwsObject.serialize();

    }


    /**
     * 解析一个token
     * @param token
     * @return
     * @throws ParseException
     * @throws JOSEException
     */
    public static Map<String,Object> valid(String token) throws ParseException, JOSEException {
        //解析token
        JWSObject jwsObject = JWSObject.parse(token);
        //获取到载荷
        Payload payload=jwsObject.getPayload();
        //建立一个解锁密匙
        JWSVerifier jwsVerifier = new MACVerifier(secret);
        Map<String, Object> resultMap = new HashMap<>();
        //判断token
        if (jwsObject.verify(jwsVerifier)) {
            resultMap.put("Result", 0);
            //载荷的数据解析成json对象。
            JSONObject jsonObject = payload.toJSONObject();
            resultMap.put("data", jsonObject);
            //判断token是否过期
            if (jsonObject.containsKey("exp")) {
                Long expTime = Long.valueOf(jsonObject.get("exp").toString());
                Long nowTime = new Date().getTime();
                //判断是否过期
                if (nowTime > expTime) {
                    //已经过期
                    log.info("token 过期");
                    resultMap.clear();
                    resultMap.put("Result", 2);
                }
            }
        }else {
            log.info("token 检查未过");
            resultMap.put("Result", 1);
        }
        return resultMap;
    }


    /**
     * 生成一个token
     * @param payloadMap
     * @param keySecret 不能少于32位
     * @return
     * @throws JOSEException
     */
    public static String creatToken(Map<String,Object> payloadMap,String keySecret) throws JOSEException {
        //3.先建立一个头部Header
        /**
         * JWSHeader参数：1.加密算法法则,2.类型，3.。。。。。。。
         * 一般只需要传入加密算法法则就可以。
         * 这里则采用HS256
         *
         * JWSAlgorithm类里面有所有的加密算法法则，直接调用。
         */
        JWSHeader jwsHeader = new JWSHeader(JWSAlgorithm.HS256);
        // 建立一个载荷Payload
        Payload payload = new Payload(new JSONObject(payloadMap));

        // 将头部和载荷结合在一起
        JWSObject jwsObject = new JWSObject(jwsHeader, payload);
        // 建立一个密匙
        JWSSigner jwsSigner = new MACSigner(keySecret.getBytes());
        // 签名
        jwsObject.sign(jwsSigner);
        // 生成token
        return jwsObject.serialize();

    }


    /**
     * 解析一个token
     * @param token
     * @param keySecret 不能少于32位
     * @return
     * @throws ParseException
     * @throws JOSEException
     */
    public static Map<String,Object> valid(String token, String keySecret) throws ParseException, JOSEException {
        //解析token
        JWSObject jwsObject = JWSObject.parse(token);
        //获取到载荷
        Payload payload=jwsObject.getPayload();
        //建立一个解锁密匙
        JWSVerifier jwsVerifier = new MACVerifier(keySecret.getBytes());
        Map<String, Object> resultMap = new HashMap<>();
        //判断token
        if (jwsObject.verify(jwsVerifier)) {
            resultMap.put("Result", 0);
            //载荷的数据解析成json对象。
            JSONObject jsonObject = payload.toJSONObject();
            resultMap.put("data", jsonObject);
            //判断token是否过期
            if (jsonObject.containsKey("exp")) {
                Long expTime = Long.valueOf(jsonObject.get("exp").toString());
                Long nowTime = new Date().getTime();
                //判断是否过期
                if (nowTime > expTime) {
                    //已经过期
                    log.info("token 过期");
                    resultMap.clear();
                    resultMap.put("Result", 2);
                }
            }
        }else {
            log.info("token 检查未过");
            resultMap.put("Result", 1);
        }
        return resultMap;
    }


}
